﻿using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Win32;
using RollcallClient.Localhost;
using System.Windows.Forms;
using System.Threading;
using System.IO;
using log4net;
using System.Diagnostics;
using System.Net.NetworkInformation;

namespace RollCallClient
{
    class RollcallMain : IDisposable
    {
        static ILog logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

        //Represents a key-level node in the Windows registry. 
        RegistryKey rkApp = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true);
        //Checker is a singleton
        private static readonly RollcallMain rollCall = new RollcallMain();
        // Register a Service and using its method 
        static Service ser;
        //Registe a UserInfo to use it method
        static UserInfo USInfo;
        //this variable show that Checking is OK or not
        public bool bChecked = false;
        //Close app and release resource
        bool IsDisposing = false;
        //Specifies a component that creates an icon in the notification area.
        static NotifyIcon notify;
        //Represents a Windows icon, which is a small bitmap image used to represent
        //an object.
        System.Drawing.Icon icon;
        //Represents a shortcut menu.
        ContextMenu contextmenu = new ContextMenu();
        //Get value of CheckSuccess
        public bool GetCheckSuccess()
        {
            return bChecked;
        }
        /// <summary>
        /// this function use when user recheck attend
        /// </summary>
        public void ReCheckAttend()
        {
            //When the Checking was not done!
            while (!bChecked)
            {   //When connect is available
                if (USInfo.IsInternetConnected())
                {
                    try
                    {   //Flag used to get value from server responsed.
                        //With each value it got, we know the attendence status, server  
                        int intFlag = ser.CheckAttendance(USInfo.GetUserName(), GetCurrentMACAddress(), "84ac41d7c57ea25694b0cb7899a104f5");
                        
                        //if flag  = 1, -> user has just had attendence done!
                        if (intFlag == 1)
                        {
                            //Show balloon to make user known
                            //type of balloon is Information                            
                            notify.BalloonTipIcon = ToolTipIcon.Info;
                            //title is "Notice"
                            notify.BalloonTipTitle = "Notice!";
                            //Content of balloon
                            notify.BalloonTipText = "Your attendance was checked successful!";
                            //Time of showing balloon
                            notify.ShowBalloonTip(1000);
                            //Mark CheckSuccess is true
                            bChecked = true;

                        }
                            //flag = 2, show that In database has no that name
                        else if (intFlag == 2)
                        {
                            //DialogResult ask user if want to setting again
                            DialogResult dlgResult = MessageBox.Show
                            ("Username is wrong or not available.\nDo you want to resetting ?\n(No: Stop autocheck)",
                             "", MessageBoxButtons.YesNo, MessageBoxIcon.Error);
                            //If User wannt to enter his or her Username again
                            if (dlgResult == DialogResult.Yes)
                            {
                                //Show InfoSetting Form for user
                                (new InfoSetting()).ShowDialog();
                                //Read User Info  
                                USInfo.ReadUserInfoFromFile();
                            }
                            //If user dont wanna resetting
                            else
                            {
                                //Show balloon to make user known
                                //type of balloon is Information   
                                notify.BalloonTipIcon = ToolTipIcon.Info;
                                //title is "Notice"
                                notify.BalloonTipTitle = "Notice!";
                                //Content of balloon
                                notify.BalloonTipText = "You are stop auto check attendance!";
                                //Time of showing balloon
                                notify.ShowBalloonTip(1000);
                                //Mark CheckSuccess is true
                                bChecked = true;
                            }
                        }
                        //Mean that User has checked attendance before
                        else if (intFlag == 0)
                        {
                            notify.BalloonTipIcon = ToolTipIcon.Info;
                            notify.BalloonTipTitle = "Notice!";
                            notify.BalloonTipText = "You have checked attendance already!!\n Check attendace once a day.";
                            notify.ShowBalloonTip(1000);
                            Thread.CurrentThread.Abort();
                        }
                    }
                    catch
                    {
                    }
                }
                //Suspends the current thread for a specified time.
                Thread.Sleep(2000);
            }
        }
        /// <summary>
        /// return rollcall
        /// </summary>
        /// <returns></returns>
        public static RollcallMain GetRollcalMainObject()
        {
            return rollCall;
        }
        /// <summary>
        /// when user click exit button
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void tmn_Exit_Click(object sender, EventArgs e)
        {
            logger.Info("Exit menu click");
            //Message box for confirm 
            //Get the button Yes or No that user has entered
            //q is question
            DialogResult dlgResult = MessageBox.Show("Do you want to exit RollcalClient?", "Message!", 
                        MessageBoxButtons.YesNo, MessageBoxIcon.Question);
            //If User still want to exit
            if (dlgResult == DialogResult.Yes)
            {
                //Raises a System.Threading.ThreadAbortException in the thread on which it
                //is invoked, to begin the process of terminating the thread.
                this.Dispose();
                Thread.CurrentThread.Abort();
                //Close app
                //Write to log file
                
            }
        }
        /// <summary>
        /// Help menu click
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void tmn_Help_Click(object sender, EventArgs e)
        {
            //Start new process
            Process pHelp = new Process();
            //Name of parameter, here is Internet Explore, to run Help file
            pHelp.StartInfo.FileName = "iexplore.exe";
            //Specify file to run with IE, here is Help.htm
            pHelp.StartInfo.Arguments = Path.GetDirectoryName(Application.ExecutablePath) + "\\Help.htm";
            //Start process
            pHelp.Start();
        }

        //Check attendance yourseft, not auto
        private void tmn_CheckAttend_Click(object sender, EventArgs e)
        {
            //Log info
            logger.Info("Check attendance by hand.");
            //Do check
            UserChecking();
        }

        //Show setting board form to configure
        private void tmn_Setting_Click(object sender, EventArgs e)
        {
            //log fiel
            logger.Info("Show Inforsetting form");
            //Show dialog
            (new InfoSetting()).ShowDialog();
            //Read setting info to load it to form correctly
            USInfo.ReadUserInfoFromFile();

        }

        private RollcallMain() //singleton so private constructor!
        {
            log4net.Config.XmlConfigurator.Configure();
            if (rkApp.GetValue("RollcalClient") == null)
            {
                // The value doesn't exist, the application is not set to run at startup
                rkApp.SetValue("RollcalClient", Application.ExecutablePath.ToString());
            }
            //create a instance of service to use afterward
            ser = new Service();

            //create menu
            //popup contextmenu when doubleclick or when click in the menu.
            //and run correspond function
            MenuItem mnuItemSetting = new MenuItem("Setting", new EventHandler(tmn_Setting_Click));
            contextmenu.MenuItems.Add(mnuItemSetting);
            //popup contextmenu when doubleclick or when click in the menu.
            //and run correspond function
            MenuItem mnuItemChecking = new MenuItem("Check attendance", new EventHandler(tmn_CheckAttend_Click));
            contextmenu.MenuItems.Add(mnuItemChecking);
            //popup contextmenu when doubleclick or when click in the menu.
            //and run correspond function
            MenuItem mnuItemHelp = new MenuItem("Help", new EventHandler(tmn_Help_Click));
            contextmenu.MenuItems.Add(mnuItemHelp);
            //add a exit submenu item
            mnuItemSetting = new MenuItem("Exit", new EventHandler(Menu_OnExit));
            contextmenu.MenuItems.Add(mnuItemSetting);


            //Initializes a new instance of the System.Windows.Forms.NotifyIcon class.
            notify = new NotifyIcon();
            try
            {
                //get path of installed program
                string strAppPath = Path.GetDirectoryName(Application.ExecutablePath);
                //assign an image for icon
                icon = new System.Drawing.Icon(strAppPath + "\\icon.ICO");
                //assign icon to notify
                notify.Icon = icon;
            }
            //trap errors
            catch (IOException ex)
            {
                //print error
                MessageBox.Show(ex.Message);
                //log error to file
                logger.Debug(ex.Message);
                //log event exit to file
                logger.Debug("RollCall Exit");
                //close threads
                Application.ExitThread();
                //close app
                Application.Exit();
            }
            //add text to notiy, when user put the pointer on icon
            notify.Text = "RollcallClient";
            //add menu ro notify
            notify.ContextMenu = contextmenu;
            //Make notify visible
            notify.Visible = true;
            //create a instance of UserInfo class for get information of current user
            USInfo = new UserInfo();
            //Load data
            LoadData();

            if (USInfo.CheckDay())
            {
                UserChecking();
            }
            else
            {
                notify.BalloonTipIcon = ToolTipIcon.Info;
                notify.BalloonTipTitle = "Notice!";
                notify.BalloonTipText = "You didn't set check attendance today.\nRollCall not auto check attendance for you!";
                notify.ShowBalloonTip(1000);
                logger.Info(notify.BalloonTipText);
                bChecked = true;
            }
        }
        /// <summary>
        /// Load data from file and show it in setting form
        /// </summary>
        public void LoadData()
        {
            //reading file is OK
            if (USInfo.ReadUserInfoFromFile())
            {
                //Write to log file
                logger.Info("RollcallClient Load data successful!");
            }
            //if Reading file is fail
            else
            {
                //If not exist RollCallclient directory
                if (!(File.Exists((Environment.SpecialFolder.MyDocuments) + "\\RollCallClient")))
                {
                    //Create it
                    Directory.CreateDirectory(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "\\RollCallClient");
                }
                //Show a balloon 
                notify.BalloonTipIcon = ToolTipIcon.Info;
                //title of that balloon is Notie
                notify.BalloonTipTitle = "Notice!";
                //Context of balloon tell user that: Rollcall can load data...
                notify.BalloonTipText = "RollcallClient can not Load data!\nPle"
                + "ase setting for RollcalClient.";
                //time of live of notify
                notify.ShowBalloonTip(1000);
                //Write to log file
                logger.Info(notify.BalloonTipText);
                //Show setting form
                (new InfoSetting()).ShowDialog();
                //Read information from file
                USInfo.ReadUserInfoFromFile();
            }

        }

        /// <summary>
        /// user check
        /// </summary>
        public void UserChecking()
        {
            //If connection is OK
            if (USInfo.IsInternetConnected())
            {
                //do
                try
                {
                    //get result from server
                    int IntFlag = ser.CheckAttendance(USInfo.GetUserName(), GetCurrentMACAddress(), "84ac41d7c57ea25694b0cb7899a104f5");
                    //Can't connect to server (althought connection is OK)
                   if (IntFlag == -1)
                    {
                        //Show balloon 
                        notify.BalloonTipIcon = ToolTipIcon.Info;
                        //assign title
                        notify.BalloonTipTitle = "Error! " + USInfo.GetUserName() + GetCurrentMACAddress();
                        //assign text to balloon
                        notify.BalloonTipText = "Error accur at server.\n You can not check attendance at this time!";
                        //Time of live of notify
                        notify.ShowBalloonTip(1000);
                        //Write to log file
                        logger.Info(notify.BalloonTipText);
                    }
                    // user has checked attendance
                    else if (IntFlag == 0)
                    {
                        //Show balloon
                        notify.BalloonTipIcon = ToolTipIcon.Info;
                        //Title of balloon
                        notify.BalloonTipTitle = "Notice!";
                        //Text of balloon
                        notify.BalloonTipText = "Today you was checked attendance!\n Check attendace 1 time per day.";
                        //time of live
                        notify.ShowBalloonTip(1000);
                        //Write to log file
                        logger.Info(notify.BalloonTipText);
                        //mark user as checked
                        bChecked = true;

                    }

                    //Show that now user's attendence is OK
                    else if (IntFlag == 1)
                    {
                        //Show balloon
                        notify.BalloonTipIcon = ToolTipIcon.Info;
                        //Title of balloon
                        notify.BalloonTipTitle = "Notice!";
                        //text of balloon
                        notify.BalloonTipText = "You are checked attendance successful!";
                        //time of live of balloon
                        notify.ShowBalloonTip(1000);
                        //write to log file
                        logger.Info(notify.BalloonTipText);
                        //Mark user as checked
                        bChecked = true;

                    }
                    //username is not avalable
                    else if (IntFlag == 2)
                    {
                        //temp string 
                        String mss = "Username is wrong or not available.\nDo you want to resetting ?";
                        //write to log file
                        logger.Info(mss);
                        //if user has not checked attendance
                        if (!bChecked)
                        {
                            //add more text to temp string
                            mss += "\n(No: Stop auto check loging!)";
                        }
                        //create a dialog resuft for return User's Retry decision
                        DialogResult dlgResult = MessageBox.Show(mss, "", MessageBoxButtons.YesNo, MessageBoxIcon.Error);
                        //write to log file
                        logger.Info(dlgResult.ToString());
                        //user wanna recheck
                        if (dlgResult == DialogResult.Yes)
                        {
                            //Show setting form
                            (new InfoSetting()).ShowDialog();
                            //read data file for load correct form
                            USInfo.ReadUserInfoFromFile();
                        }
                        //user dont wanna rechecked
                        else
                        {
                            //? mark user as checked
                            bChecked = true;
                        }
                    }
                }
                //trap error
                catch (Exception ez)
                {
                    //Error icon in balloon
                    notify.BalloonTipIcon = ToolTipIcon.Error;
                    //Title of balloon
                    notify.BalloonTipTitle = "Error!";
                    //Text of message is error message
                    notify.BalloonTipText = ez.Message;
                    //Time of live of balloon
                    notify.ShowBalloonTip(1000);
                    //Write log to file
                    logger.Error(notify.BalloonTipText);
                    //MessageBox.Show("Error accur:"+ex.Message, "Error!", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
            //Connection is not avalable
            else
            {
                //Text of balloon
                notify.BalloonTipText = "You are not connect to internet now.\n Rollcall auto check attendance when connection available.";
                //type of icon is warning
                notify.BalloonTipIcon = ToolTipIcon.Warning;
                //Title of balloon
                notify.BalloonTipTitle = "Warring !";
                //time of live of balloon
                notify.ShowBalloonTip(1000);
                //Write to log file
                logger.Error(notify.BalloonTipText);
            }
        }
        /// <summary>
        /// get mac address
        /// </summary>
        /// <returns></returns>
        public String GetCurrentMACAddress()
        {
            // Browse all network interface to return right mac address

            //return Mac address when connected by Wifi
            foreach (NetworkInterface ni in NetworkInterface.GetAllNetworkInterfaces())
            {   //Gets the current operational state of the network connection.
                //and check the network interface is up; it can transmit data packets.
                if (ni.OperationalStatus == OperationalStatus.Up &&
                    //and check if the network interface is unable to transmit data packets because of a missing
                    //component, typically a hardware component.
                        ni.OperationalStatus != OperationalStatus.NotPresent &&
                    //Check if the network interface uses a tunnel connection.
                    //if yes, we can't get Mac address
                            ni.NetworkInterfaceType != NetworkInterfaceType.Tunnel &&
                    //Check if the network interfacs is a loopback adapter.
                    //if yes, it's just for testing; no traffic is sent.
                                ni.NetworkInterfaceType != NetworkInterfaceType.Loopback &&
                    //The network interface uses a wireless LAN connection (IEEE 802.11 standard).
                                        ni.NetworkInterfaceType == NetworkInterfaceType.Wireless80211)
                {
                    //return mac address
                    return ni.GetPhysicalAddress().ToString();
                }
                //return mac address when connected by Ethernet
                if (ni.NetworkInterfaceType == NetworkInterfaceType.Ethernet &&
                    //Gets the current operational state of the network connection.
                    //and check the network interface is up; it can transmit data packets.
                        ni.OperationalStatus == OperationalStatus.Up)
                {
                    //return mac address
                    return ni.GetPhysicalAddress().ToString();
                }
            }
            //if there's no mac address, return NULL
            return null;
        }
        //Destructor
        ~RollcallMain()
        {
            //Close app and exit all related process
            Dispose();
        }
        /// <summary>
        /// 
        /// </summary>
        public void Dispose()
        {
            //Check if IsDisposing is fail
            if (!IsDisposing)
            {
                //timer.Stop();
                //assign it from false to true
                IsDisposing = true;
                //write to log gile
                logger.Info("Rollcal exit success.");
                //Exit app
                Application.Exit();
            }
        }
        /// <summary>
        /// when user click exit menu
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void Menu_OnExit(Object sender, EventArgs e)
        {
            //Show a dialog result for confirm 
            DialogResult dlgResult = MessageBox.Show("Do you want to exit RollcalClient?", "Message!", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
            //User really want to exit
            if (dlgResult == DialogResult.Yes)
            {
                //be sure to call Application.Exit
                //Call dispose
                Dispose();
                //Exit app
                Application.Exit();
            }
        }
    }
}
